package com.gack.netty.server;

import java.io.IOException;
import java.net.InetSocketAddress;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.gack.netty.initializer.NettyServerInitializer;
import com.gack.netty.util.common.ServerMessageTypeToClassUtil;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;

/**
 * 
* @ClassName: NettyPushServer 
* @Description: TODO(这里用一句话描述这个类的作用) 
* @author (ZhangXinYu)  
* @date 2018年8月30日 下午2:34:55 
* @version V1.0
 */
@Component
@Slf4j
public class NettyPushServer {
	@Autowired
	private NettyServerInitializer nettyServerInitializer;

	@Value("${netty.host}")
	private String HOST;
	@Value("${netty.port}")
	private int PORT;
	@Value("${netty.channel.backlog}")
	private int BACKLOG;
	@Value("${netty.childChannel.keepAlive}")
	private boolean KEEPALIVE;
	@Value("${netty.bossNumber}")
	private int BOSS_NUMBER;
	@Value("${netty.workerNumber}")
	private int WORKER_NUMBER;
	@Value("${netty.scan_service_annotation_path}")
	private String scanAnnotationPath;
	
	private ChannelFuture future;
	private EventLoopGroup bossGroup;
	private EventLoopGroup workerGroup;
	
	
	@PostConstruct
	public void start() throws InterruptedException, IOException, ClassNotFoundException{
		// init MessageTypeToClassMap
		ServerMessageTypeToClassUtil.initTypeToMsgClassMap(scanAnnotationPath);
		
		bossGroup = new NioEventLoopGroup(this.BOSS_NUMBER);
		workerGroup = new NioEventLoopGroup(this.WORKER_NUMBER);
		ServerBootstrap serverBootstrap = new ServerBootstrap();
		serverBootstrap.group(bossGroup,workerGroup)
			.channel(NioServerSocketChannel.class)
			.option(ChannelOption.SO_BACKLOG, BACKLOG)
			.handler(new LoggingHandler(LogLevel.INFO))
			.childOption(ChannelOption.SO_KEEPALIVE, KEEPALIVE)
//			.childOption(ChannelOption.SO_BACKLOG, BACKLOG)
			.childHandler(nettyServerInitializer);
		this.future = serverBootstrap.bind(new InetSocketAddress(HOST, PORT)).syncUninterruptibly();
		log.info("-------------------------NETTY INFO-------------------------");
		log.info("netty服务在端口 ["+this.PORT+"] 启动成功");
	}
	
	@PreDestroy
	public void stop(){
		System.out.println("destroy server resources");
		if(future == null || future.channel() == null){
			System.out.println("channel is null");
		}
		bossGroup.shutdownGracefully();
		workerGroup.shutdownGracefully();
		future.channel().closeFuture().syncUninterruptibly();
		bossGroup = null;
		workerGroup = null;
		future = null;
	}
}
